<template>
  <div class="fc-style">
    <el-container class="fc-container">
      <el-main class="fc-main">
        <el-container>
          <!-- 左侧字段组件 -->
          <el-aside width="250px">
            <div class="components">
              <ComponentGroup title="基础字段" :fields="basicFields" :list="element.basicComponents" />
              <ComponentGroup title="高级字段" :fields="advanceFields" :list="element.advanceComponents" />
              <ComponentGroup title="布局字段" :fields="layoutFields" :list="element.layoutComponents" />
            </div>
          </el-aside>

          <!-- 中间表单设计 -->
          <el-main class="center-container">
            <ElCustomHeader
              v-bind="props"
              @preview="() => (previewVisible = true)"
              @uploadJson="() => (uploadJsonVisible = true)"
              @generateJson="handleGenerateJson"
              @generateCode="handleGenerateCode"
              @clearable="handleClearable"
            >
              <slot name="header"></slot>
            </ElCustomHeader>

            <el-main :class="{ 'widget-empty': widgetForm.list.length === 0 }">
              <ElWidgetForm ref="widgetFormRef" v-model:widgetForm="widgetForm" v-model:widgetFormSelect="widgetFormSelect" />
            </el-main>
          </el-main>

          <!-- 右侧字段属性配置 -->
          <el-aside class="widget-config-container" width="300px">
            <el-container>
              <el-header>
                <div class="config-tab" :class="{ active: configTab === 'widget' }" @click="configTab = 'widget'">字段属性</div>
                <div class="config-tab" :class="{ active: configTab === 'form' }" @click="configTab = 'form'">表单属性</div>
              </el-header>
              <el-main class="config-content">
                <ElWidgetConfig v-show="configTab === 'widget'" v-model:select="widgetFormSelect" />
                <ElFormConfig v-show="configTab === 'form'" v-model:config="widgetForm.config" />
              </el-main>
            </el-container>
          </el-aside>
        </el-container>
      </el-main>

      <!-- JSON 导入弹窗 -->
      <el-dialog v-model="uploadJsonVisible" title="导入JSON" :width="800">
        <el-alert type="info" title="JSON格式如下，直接复制生成的json覆盖此处代码点击确定即可" style="margin-bottom: 10px" />
        <CodeEditor v-model:value="jsonEg" language="json" />
        <template #footer>
          <el-button @click="() => (uploadJsonVisible = false)">取消</el-button>
          <el-button type="primary" @click="handleUploadJson">导入</el-button>
        </template>
      </el-dialog>

      <!-- 表单预览 -->
      <el-dialog v-model="previewVisible" title="预览" :width="800">
        <ElGenerateForm ref="generateFormRef" v-if="previewVisible" :data="widgetForm" />
        <template #footer>
          <el-button @click="handleReset">重置</el-button>
          <el-button type="primary" @click="handleGetData">获取数据</el-button>
        </template>

        <!-- 获取数据弹窗 -->
        <el-dialog v-model="dataJsonVisible" title="获取数据" :width="800">
          <CodeEditor :value="dataJsonTemplate" language="json" readonly />
          <template #footer>
            <el-button @click="() => (dataJsonVisible = false)">取消</el-button>
            <el-button type="primary" @click="handleCopyClick(dataJsonTemplate)">Copy</el-button>
          </template>
        </el-dialog>
      </el-dialog>

      <!-- 生成 JSON 弹窗 -->
      <el-dialog v-model="generateJsonVisible" title="生成JSON" :width="800">
        <CodeEditor :value="generateJsonTemplate" language="json" readonly />
        <template #footer>
          <el-button @click="() => (generateJsonVisible = false)">取消</el-button>
          <el-button type="primary" @click="handleCopyClick(generateJsonTemplate)">Copy</el-button>
        </template>
      </el-dialog>

      <!-- 生成代码弹窗 -->
      <el-dialog v-model="dataCodeVisible" title="生成代码" :width="800">
        <el-tabs type="card" v-model="codeLanguage" :tabBarStyle="{ margin: 0 }">
          <el-tab-pane label="Vue Component" :name="codeType.Vue">
            <CodeEditor :value="dataCodeTemplate" language="html" readonly />
          </el-tab-pane>
          <el-tab-pane label="HTML" :name="codeType.Html">
            <CodeEditor :value="dataCodeTemplate" language="html" readonly />
          </el-tab-pane>
        </el-tabs>
        <template #footer>
          <el-button @click="() => (dataCodeVisible = false)">取消</el-button>
          <el-button type="primary" @click="handleCopyClick(dataCodeTemplate)">Copy</el-button>
        </template>
      </el-dialog>
    </el-container>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, watchEffect } from 'vue';
import { ElMessage } from 'element-plus';
import { defaultsDeep } from 'lodash';
import CodeEditor from '../components/CodeEditor.vue';
import ComponentGroup from '../components/ComponentGroup.vue';
import ElCustomHeader from './ElCustomHeader.vue';
import ElWidgetForm from './ElWidgetForm.vue';
import ElGenerateForm from './ElGenerateForm.vue';
import ElWidgetConfig from './ElWidgetConfig.vue';
import ElFormConfig from './ElFormConfig.vue';
import { element } from '../config';
import { copy } from '../utils';
import { CodeType } from '../enums';
import generateCode from '../utils/generateCode';
import type { WidgetForm } from '../config/element';

const props = defineProps({
  preview: Boolean,
  generateCode: Boolean,
  generateJson: Boolean,
  uploadJson: Boolean,
  clearable: Boolean,
  basicFields: { type: Array as () => string[], default: () => [] },
  advanceFields: { type: Array as () => string[], default: () => [] },
  layoutFields: { type: Array as () => string[], default: () => [] }
});

const widgetForm = ref<WidgetForm>(JSON.parse(JSON.stringify(element.widgetForm)));
const widgetFormSelect = ref();
const configTab = ref<'widget' | 'form'>('widget');
const previewVisible = ref(false);
const uploadJsonVisible = ref(false);
const dataJsonVisible = ref(false);
const dataCodeVisible = ref(false);
const generateJsonVisible = ref(false);
const dataCodeTemplate = ref('');
const generateJsonTemplate = ref(JSON.stringify(widgetForm.value, null, 2));
const dataJsonTemplate = ref('');
const jsonEg = ref(JSON.stringify(widgetForm.value, null, 2));
const codeLanguage = ref<CodeType>(CodeType.Vue);
const codeType = CodeType;

const widgetFormRef = ref<InstanceType<typeof ElWidgetForm> | null>(null);
const generateFormRef = ref<InstanceType<typeof ElGenerateForm> | null>(null);

function handleUploadJson() {
  try {
    widgetForm.value.list = [];
    defaultsDeep(widgetForm.value, JSON.parse(jsonEg.value));
    if (widgetForm.value.list?.length) {
      widgetFormSelect.value = widgetForm.value.list[0];
    }
    uploadJsonVisible.value = false;
    ElMessage.success('上传成功');
  } catch (err) {
    ElMessage.error('上传失败');
  }
}

function handleCopyClick(text: string) {
  copy(text);
  ElMessage.success('Copy成功');
}

function handleGetData() {
  generateFormRef.value?.getData().then((res: any) => {
    dataJsonTemplate.value = JSON.stringify(res, null, 2);
    dataJsonVisible.value = true;
  });
}

function handleGenerateJson() {
  generateJsonTemplate.value = JSON.stringify(widgetForm.value, null, 2);
  generateJsonVisible.value = true;
}

function handleGenerateCode() {
  codeLanguage.value = CodeType.Vue;
  dataCodeVisible.value = true;
}

watchEffect(() => {
  if (dataCodeVisible.value) {
    dataCodeTemplate.value = generateCode(widgetForm.value, codeLanguage.value)!;
  }
});

function handleClearable() {
  widgetForm.value.list = [];
  defaultsDeep(widgetForm.value, JSON.parse(JSON.stringify(element.widgetForm)));
  widgetFormSelect.value = undefined;
}

function handleReset() {
  generateFormRef.value?.reset();
}

function getJson() {
  return widgetForm.value;
}

function setJson(json: WidgetForm) {
  widgetForm.value.list = [];
  defaultsDeep(widgetForm.value, json);
  if (json.list.length) {
    widgetFormSelect.value = json.list[0];
  }
}

function getTemplate(type: CodeType) {
  return generateCode(widgetForm.value, type);
}

function clear() {
  handleClearable();
}

defineExpose({
  getJson,
  setJson,
  getTemplate,
  clear
});
</script>

<style scoped>
.fc-style {
  height: 100%;
}
.fc-container {
  height: 100%;
}
.fc-main {
  padding: 0;
}
.components {
  padding: 10px;
}
.center-container {
  padding: 10px;
}
.widget-config-container {
  border-left: 1px solid #e0e0e0;
}
.config-tab {
  display: inline-block;
  padding: 10px 16px;
  cursor: pointer;
}
.config-tab.active {
  font-weight: bold;
  color: #409eff;
  border-bottom: 2px solid #409eff;
}
.config-content {
  padding: 10px;
}
</style>
